#include <sdl.hpp>
#include <iostream>
#include <string>

std::string getFlag(Uint32 flags) {
  std::string str;
  if (flags & SDL_RENDERER_SOFTWARE) str += "software ";
  else if (flags & SDL_RENDERER_ACCELERATED) str += "accelerated ";
  else if (flags & SDL_RENDERER_PRESENTVSYNC) str += "presentVsync ";
  else if (flags & SDL_RENDERER_TARGETTEXTURE) str += "targetTexture ";
  return std::move(str);
}
const char* getFmt(Uint32 fmt) {
  return SDL_GetPixelFormatName(fmt);
}
std::string getRect(const sdl::Rect &rc) {
  std::string str;
  str += "x: ";
  str += std::to_string(rc.x);
  str += ", y: ";
  str += std::to_string(rc.y);
  str += ", w: ";
  str += std::to_string(rc.w);
  str += ", h: ";
  str += std::to_string(rc.h);
  return std::move(str);
}
std::string getDPI(float ddpi, float hdpi, float vdpi) {
  std::string str;
  str += "ddpi: ";
  str += std::to_string(ddpi);
  str += ", hdpi: ";
  str += std::to_string(hdpi);
  str += ", vdpi: ";
  str += std::to_string(vdpi);
  return std::move(str);
}
const char* getDisplayOrientation(sdl::display::Orientation sdo) {
  switch (sdo) {
    case sdl::display::Orientation::SDL_ORIENTATION_UNKNOWN: return "Unknown";
    case sdl::display::Orientation::SDL_ORIENTATION_LANDSCAPE: return "LandScape";
    case sdl::display::Orientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED: return "LandScapeFlipped";
    case sdl::display::Orientation::SDL_ORIENTATION_PORTRAIT: return "Portrait";
    case sdl::display::Orientation::SDL_ORIENTATION_PORTRAIT_FLIPPED: return "PortraitFlipped";
  }
  return "";
}

void showRenderInfo() {
  sdl::Renderer::Info info;
  auto count = sdl::Renderer::getNumDrivers();
  std::cout << "RenderDrivers: " << count << std::endl;

  for (int i = 0; i < count; ++i) {
    std::cout << "----- RenderDriver " << i << " -----" << std::endl;
    if (sdl::isFailed(sdl::Renderer::getInfo(i, &info))) {
      std::cout << "ERROR." << std::endl;
      continue;
    }
    std::cout << "Name: " << info.name << std::endl;
    std::cout << "Flags: " << getFlag(info.flags) << std::endl;
    std::cout << "Texture: " << info.num_texture_formats << std::endl;
    std::cout << "  width: " << info.max_texture_width << std::endl;
    std::cout << "  height: " << info.max_texture_height << std::endl;
    std::cout << "  PixelFormate: ";
    for (int j = 0; j < info.num_texture_formats; ++j) {
      std::cout << getFmt(info.texture_formats[i]) << " ";
    }
    std::cout << std::endl;
  }
}

void showDisplayMode(const sdl::display::Mode &mode) {
  std::cout << "  PixelFormate: " << getFmt(mode.format) << std::endl;
  std::cout << "  width: " << mode.w << std::endl;
  std::cout << "  height: " << mode.h << std::endl;
  std::cout << "  RefreshRate: " << mode.refresh_rate << std::endl;
}
void showVideoDisplayInfo(int displayIndex) {
  std::cout << "----- VideoDisplay " << displayIndex << " -----" << std::endl;
  std::cout << "Name: " << sdl::display::getName(displayIndex) << std::endl;

  sdl::Rect rc;
  sdl::display::getBounds(displayIndex, &rc);
  std::cout << "Bounds: " << getRect(rc) << std::endl;

  sdl::display::getUsableBounds(displayIndex, &rc);
  std::cout << "UsableBounds: " << getRect(rc) << std::endl;

  float ddpi, hdpi, vdpi;
  sdl::display::getDPI(displayIndex, &ddpi, &hdpi, &vdpi);
  std::cout << "DPI: " << getDPI(ddpi, hdpi, vdpi) << std::endl;

  std::cout << "Orientation: " << getDisplayOrientation(
    sdl::display::getOrientation(displayIndex)) << std::endl;

  sdl::display::Mode mode;
  int count = sdl::display::getNumModes(displayIndex);
  std::cout << "DisplayModes: " << count << std::endl;
  for (int i = 0; i < count; ++i) {
    std::cout << "  ----- DisplayMode " << i << " -----" << std::endl;
    if (sdl::isFailed(sdl::display::getMode(displayIndex, i, &mode))) {
      std::cout << "ERROR." << std::endl;
      continue;
    }
    showDisplayMode(mode);
  }

  sdl::display::getDesktopMode(displayIndex, &mode);
  std::cout << "DesktopDisplayMode: " << std::endl;
  showDisplayMode(mode);

  sdl::display::getCurrentMode(displayIndex, &mode);
  std::cout << "CurrentDisplayMode: " << std::endl;
  showDisplayMode(mode);
}
void showVideoInfo() {
  auto count = sdl::display::getNumVideoDrivers();
  std::cout << "VideoDrivers: " << count << std::endl;
  for (int i = 0; i < count; ++i) {
    std::cout << "  " << i << ":";
    std::cout << sdl::display::getVideoDriver(i) << std::endl;
  }
  std::cout << "CurrentVideoDriver: " << sdl::display::getCurrentVideoDriver()
    << std::endl;
  
  std::cout << "----------" << std::endl;
  count = sdl::display::getNum();
  std::cout << "VideoDisplays: " << count << std::endl;
  for (int i = 0; i < count; ++i) {
    showVideoDisplayInfo(i);
  }
}

int main(int argc, char *argv[]) {
  auto rst = sdl::init(SDL_INIT_EVERYTHING);
  if (sdl::isFailed(rst)) {
    std::cout << "error init." << std::endl;
    return -1;
  }

  showRenderInfo();
  std::cout << "--------------------------" << std::endl;
  showVideoInfo();

  sdl::quit();
  return 0;
}